/*
 * Copyright (c) 2025 Huawei Device, Inc. Ltd. and <马弓手>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "FileUtils.h"
#include "cJSON.h"
#include "FileCache.h"
#include <cstddef>
#include <sys/stat.h>
#include <filemanagement/file_uri/oh_file_uri.h>
#include <unistd.h>

REGISTER_PLUGIN_CLASS(FileUtils)
vector<CFilesystem::Filesystem> FileUtils::m_vecFilesystems;
bool FileUtils::execute(const string&  actionAsString, cJSON* args, CallbackContext cbc)
{
    //插件先初始化，文件系统后初始化
    if(m_vecFilesystems.size() == 0) {
        m_vecFilesystems = CFilesystem::getFileSystem();
    }
    
    if(actionAsString == "onArKTsResult") {
        return onArKTsResult(args);
    }
    
    if(actionAsString == "testSaveLocationExists") {
       PluginResult pluginResult(PluginResult::Status::OK, true);
       cbc.sendPluginResult(pluginResult) ;
       return true; 
    } else if(actionAsString == "getFreeDiskSpace") {
        m_cbc = cbc;
        return executeArkTs("./PluginAction/GetFreeSpace/GetFreeSpace", 0, "", "File", cbc);
    } else if(actionAsString == "testFileExists") {
        if(cJSON_GetArraySize(args) < 1) {
            cbc.error(ABORT_ERR);
            return true;
        }
        string fName = cJSON_GetArrayItem(args, 0)->valuestring;
        fName = CFilesystem::getNativeUrl(fName);
        
        string nativeURL =  fName;
        if(fName.find_last_of("/") != string::npos) {
            fName = fName.substr(fName.find_last_of("/")+1);
            nativeURL = fName.substr(0, fName.find_last_of("/"));
        }
                    
        bool isFile = FileCache::IsFile(fName, nativeURL);
        PluginResult pluginResult(PluginResult::Status::OK, isFile);
        cbc.sendPluginResult(pluginResult) ;
        return true; 
    } else if(actionAsString == "testDirectoryExists") {
        if(cJSON_GetArraySize(args) < 1) {
            cbc.error(ABORT_ERR);
            return true;
        }
        string fName = cJSON_GetArrayItem(args, 0)->valuestring;
        fName = CFilesystem::getNativeUrl(fName);
                        
        bool isFile = FileCache::isDirectory(fName);
        PluginResult pluginResult(PluginResult::Status::OK, isFile);
        cbc.sendPluginResult(pluginResult) ;
        return true; 
    } else if(actionAsString == "readAsText") {
        if(cJSON_GetArraySize(args) < 4) {
            cbc.error(ABORT_ERR);
            return true;
        }
        string fName = cJSON_GetArrayItem(args, 0)->valuestring;
        fName = CFilesystem::getNativeUrl(fName);

        string encoding = cJSON_GetArrayItem(args, 1)->valuestring;    
        int nStart = cJSON_GetArrayItem(args, 2)->valueint;
        int nEnd = cJSON_GetArrayItem(args, 3)->valueint;
        
        string nativeURL =  fName;
        if(fName.find_last_of("/") != string::npos) {
            fName = fName.substr(fName.find_last_of("/")+1);
        }
        if(nativeURL.find("/data") == string::npos) {//不带路径的使用root路径
            for(int i=0; i<m_vecFilesystems.size(); i++) {
                if(m_vecFilesystems[i].m_strName == "root") {
                    nativeURL = m_vecFilesystems[i].m_strRootUri + fName;
                    break;
                }
            }
        }
       long lngFileSize = FileCache::getFileSize(nativeURL);
       if(nEnd <0 || nEnd > lngFileSize) {
            nEnd = lngFileSize;
       }
       if(nStart < 0)
           nStart = 0;
       if(nStart > nEnd) {
            cbc.error(ABORT_ERR);
            return true;
       }
       const int nSize = nEnd - nStart;                     
       unsigned  char* pBuf = (unsigned char*)malloc(nSize+1);
       if(!FileCache::readFile(nativeURL, pBuf, nSize, nStart, nEnd)) {
            free(pBuf);
            cbc.error(ABORT_ERR);
            return true;
       }
       pBuf[nSize] = 0;            
       string strReadBuf = (char*)pBuf;
       free(pBuf);
       PluginResult pluginResult(PluginResult::Status::OK, strReadBuf);
       cbc.sendPluginResult(pluginResult) ;
       return true; 
    } else if(actionAsString == "readAsDataURL") {
        if(cJSON_GetArraySize(args) < 3) {
            cbc.error(ABORT_ERR);
            return true;
        }
        string fName = cJSON_GetArrayItem(args, 0)->valuestring;
        fName = CFilesystem::getNativeUrl(fName);
                                
        int nStart = cJSON_GetArrayItem(args, 1)->valueint;
        int nEnd = cJSON_GetArrayItem(args, 2)->valueint;
        
        string nativeURL =  fName;
        if(fName.find_last_of("/") != string::npos) {
            fName = fName.substr(fName.find_last_of("/")+1);
        }
        if(nativeURL.find("/data") == string::npos) {//不带路径的使用root路径
            for(int i=0; i<m_vecFilesystems.size(); i++) {
                if(m_vecFilesystems[i].m_strName == "root") {
                    nativeURL = m_vecFilesystems[i].m_strRootUri + nativeURL;
                    break;
                }
            }
        }
       long lngFileSize = FileCache::getFileSize(nativeURL);
       if(nEnd <0 || nEnd > lngFileSize) {
            nEnd = lngFileSize;
       }
       if(nStart < 0)
           nStart = 0;
       if(nStart > nEnd) {
            cbc.error(ABORT_ERR);
            return true;
       }
       const int nSize = nEnd - nStart;                     
       unsigned  char* pBuf = (unsigned char*)malloc(nSize+1);
       if(!FileCache::readFile(nativeURL, pBuf, nSize, nStart, nEnd)) {
            free(pBuf);
            cbc.error(ABORT_ERR);
            return true;
       }
       pBuf[nSize] = 0;   
       
       string strReadBuf = CBase64::encode((char*)pBuf, nSize);
       free(pBuf);
       string strContentTye =  getMimeType(fName);
       strReadBuf = "data:" +  strContentTye +";base64," + strReadBuf;
       PluginResult pluginResult(PluginResult::Status::OK, strReadBuf);
       cbc.sendPluginResult(pluginResult) ;
       return true;  
    } else if(actionAsString == "readAsArrayBuffer") {
       if(cJSON_GetArraySize(args) < 3) {
            cbc.error(ABORT_ERR);
            return true;
        }
        string fName = cJSON_GetArrayItem(args, 0)->valuestring;
        fName = CFilesystem::getNativeUrl(fName);
                                    
        int nStart = cJSON_GetArrayItem(args, 1)->valueint;
        int nEnd = cJSON_GetArrayItem(args, 2)->valueint;
        
        string nativeURL =  fName;
        if(fName.find_last_of("/") != string::npos) {
            fName = fName.substr(fName.find_last_of("/")+1);
        }
        if(nativeURL.find("/data") == string::npos) {//不带路径的使用root路径
            for(int i=0; i<m_vecFilesystems.size(); i++) {
                if(m_vecFilesystems[i].m_strName == "root") {
                    nativeURL = m_vecFilesystems[i].m_strRootUri + nativeURL;
                    break;
                }
            }
        }
       long lngFileSize = FileCache::getFileSize(nativeURL);
       if(nEnd <0 || nEnd > lngFileSize) {
            nEnd = lngFileSize;
       }
       if(nStart < 0)
           nStart = 0;
       if(nStart > nEnd) {
            cbc.error(ABORT_ERR);
            return true;
       }
       const int nSize = nEnd - nStart;                     
       unsigned  char* pBuf = (unsigned char*)malloc(nSize+1);
       if(!FileCache::readFile(nativeURL, pBuf, nSize, nStart, nEnd)) {
            free(pBuf);
            cbc.error(ABORT_ERR);
            return true;
       }
       pBuf[nSize] = 0;            
       PluginResult pluginResult(PluginResult::Status::OK, (char*)pBuf, nSize);
       free(pBuf);
       cbc.sendPluginResult(pluginResult) ;
       return true;  
    } else if(actionAsString == "readAsBinaryString") {
        if(cJSON_GetArraySize(args) < 3) {
            cbc.error(ABORT_ERR);
            return true;
        }
        string fName = cJSON_GetArrayItem(args, 0)->valuestring;
        fName = CFilesystem::getNativeUrl(fName);
        
        int nStart = cJSON_GetArrayItem(args, 1)->valueint;
        int nEnd = cJSON_GetArrayItem(args, 2)->valueint;
        
        string nativeURL =  fName;
        if(fName.find_last_of("/") != string::npos) {
            fName = fName.substr(fName.find_last_of("/")+1);
        }
        if(nativeURL.find("/data") == string::npos) {//不带路径的使用root路径
            for(int i=0; i<m_vecFilesystems.size(); i++) {
                if(m_vecFilesystems[i].m_strName == "root") {
                    nativeURL = m_vecFilesystems[i].m_strRootUri + nativeURL;
                    break;
                }
            }
        }
       long lngFileSize = FileCache::getFileSize(nativeURL);
       if(nEnd <0 || nEnd > lngFileSize) {
            nEnd = lngFileSize;
       }
       if(nStart < 0)
           nStart = 0;
       if(nStart > nEnd) {
            cbc.error(ABORT_ERR);
            return true;
       }
       const int nSize = nEnd - nStart;                     
       unsigned  char* pBuf = (unsigned char*)malloc(nSize+1);
       if(!FileCache::readFile(nativeURL, pBuf, nSize, nStart, nEnd)) {
            free(pBuf);
            cbc.error(ABORT_ERR);
            return true;
       }
       pBuf[nSize] = 0;            
       PluginResult pluginResult(PluginResult::Status::OK, (char*)pBuf, nSize, true);
       free(pBuf);
       cbc.sendPluginResult(pluginResult) ;
       return true;  
    } else if(actionAsString == "write") {
         if(cJSON_GetArraySize(args) < 4) {
            cbc.error(ABORT_ERR);
            return true;
        }
        string fName = cJSON_GetArrayItem(args, 0)->valuestring;
        fName = CFilesystem::getNativeUrl(fName);
        
        string nativeURL =  fName;
        if(fName.find_last_of("/") != string::npos) {
            fName = fName.substr(fName.find_last_of("/")+1);
        }
        if(nativeURL.find("/data") == string::npos) {//不带路径的使用root路径
            for(int i=0; i<m_vecFilesystems.size(); i++) {
                if(m_vecFilesystems[i].m_strName == "root") {
                    nativeURL = m_vecFilesystems[i].m_strRootUri + nativeURL;
                    break;
                }
            }
        }
        string data = cJSON_GetArrayItem(args, 1)->valuestring;
        int offset = cJSON_GetArrayItem(args, 2)->valueint;//0清空文件，其他：追加文件
        if(offset > 0) {
            if(!FileCache::truncateFile(nativeURL.c_str(), offset) != 0) {
                cbc.error(ABORT_ERR);
                return true;
            }
        }
        bool isBinary = false;
        if(cJSON_GetArrayItem(args, 3)->type == cJSON_True)
            isBinary = true;
        const char * pBuf =  NULL;
        int nLength = 0;
        if(isBinary) {
            pBuf = CBase64::decode(data, nLength);
        } else {
            pBuf = data.c_str();
            nLength = data.length();
        }                             
        int length = FileCache::writeFile(nativeURL, pBuf, nLength, offset);
        cbc.success(length);
    } else if(actionAsString == "truncate") {
         if(cJSON_GetArraySize(args) < 2) {
            cbc.error(ABORT_ERR);
            return true;
        }
        string fName = cJSON_GetArrayItem(args, 0)->valuestring;
        fName = CFilesystem::getNativeUrl(fName);
        
        string nativeURL =  fName;
        if(fName.find_last_of("/") != string::npos) {
            fName = fName.substr(fName.find_last_of("/")+1);
        }
        if(nativeURL.find("/data") == string::npos) {//不带路径的使用root路径
            for(int i=0; i<m_vecFilesystems.size(); i++) {
                if(m_vecFilesystems[i].m_strName == "root") {
                    nativeURL = m_vecFilesystems[i].m_strRootUri + nativeURL;
                    break;
                }
            }
        }
        int offset = cJSON_GetArrayItem(args, 1)->valueint;
        FileCache::truncateFile(nativeURL, offset);
        long lngSize = FileCache::getFileSize(nativeURL);
        PluginResult pluginResult(PluginResult::Status::OK, lngSize);
        cbc.sendPluginResult(pluginResult) ;
        return true;  
    } else if(actionAsString == "requestAllFileSystems") {
        cJSON* pJson = cJSON_CreateArray();
        for(int i=0; i<m_vecFilesystems.size(); i++) {
            cJSON* pArray = makeEntryForUrl(m_vecFilesystems[i].m_strRootUri);
            cJSON_AddItemToArray(pJson, pArray);
        }
        if(pJson != NULL) {
            cbc.success(pJson);
            cJSON_Delete(pJson);
        } else {
            cbc.error(PATH_EXISTS_ERR);
        }
    } else if(actionAsString == "requestAllPaths") {
        cJSON* pJson = requestAllPaths();
        if(pJson != NULL) {
            cbc.success(pJson);
            cJSON_Delete(pJson);
        } else {
            cbc.error(PATH_EXISTS_ERR);
        }
    } else if(actionAsString == "requestFileSystem") {
        if(cJSON_GetArraySize(args) < 2) {
            cbc.error(PATH_EXISTS_ERR);
            return true;
        }
                                                            
        int fStype = cJSON_GetArrayItem(args, 0)->valueint;
        int requiredSize = cJSON_GetArrayItem(args, 1)->valueint;
        
        CFilesystem::Filesystem system;
        if(fStype == 0) { //LocalFileSystem.js 0:TEMPORARY 1:PERSISTENT
            system = m_vecFilesystems[0];
        } else {
            system = m_vecFilesystems[1];
        }
                                                            
        cJSON* pRet = cJSON_CreateObject();
        cJSON* pJson = makeEntryForUrl(system.m_strRootUri);
        cJSON_AddStringToObject(pRet, "name", system.m_strName.c_str());
        cJSON_AddItemToObject(pRet, "root", pJson);
        cbc.success(pRet);
        cJSON_Delete(pRet);
        return true;
    } else if(actionAsString == "resolveLocalFileSystemURI") {
        if(cJSON_GetArraySize(args) < 1) {
            cbc.error(PATH_EXISTS_ERR);
            return true;
        }
        string fname = cJSON_GetArrayItem(args, 0)->valuestring;
        fname = CFilesystem::getNativeUrl(fname);
        cJSON* pJson = makeEntryForUrl(fname);
        if(pJson != NULL) {
            cbc.success(pJson);
            cJSON_Delete(pJson);
        } else {
            cbc.error(PATH_EXISTS_ERR);
        }
    } else if(actionAsString == "getFileMetadata") {
        if(cJSON_GetArraySize(args) < 1) {
            cbc.error(PATH_EXISTS_ERR);
            return true;
        }
                                                                    
        string fName = cJSON_GetArrayItem(args, 0)->valuestring;
        fName = CFilesystem::getNativeUrl(fName);
        
        string strFilePath = fName;
        if(fName.find_last_of("/") != string::npos) {
            fName = fName.substr(fName.find_last_of("/")+1);
        }
        if(strFilePath.find("/data") == string::npos) {
            for(int i=0; i<m_vecFilesystems.size(); i++) {
                if(m_vecFilesystems[i].m_strName == "root") {
                    strFilePath = m_vecFilesystems[i].m_strRootUri + strFilePath;
                    break;
                }
            }
        }
        
        cJSON* pJson = getFileMetadataForLocalURL(strFilePath, fName);
        if(pJson != NULL) {
            cbc.success(pJson);
            cJSON_Delete(pJson);
        } else {
            cbc.error(PATH_EXISTS_ERR);
        }
    } else if(actionAsString == "getParent") {
        
    } else if(actionAsString == "getDirectory") {
        if(cJSON_GetArraySize(args) < 2) {
            cbc.error(PATH_EXISTS_ERR);
            return true;
        }
        string dirname = cJSON_GetArrayItem(args, 0)->valuestring;
        string path = cJSON_GetArrayItem(args, 1)->valuestring;
        string nativeURL = CFilesystem::getNativeUrl(dirname);
        
        bool containCreate = false;
        bool exclusive = false;
        if(cJSON_GetArraySize(args) >= 3) {
            cJSON* opt = cJSON_GetArrayItem(args, 2);
            if(cJSON_GetObjectItem(opt, "create") && cJSON_GetObjectItem(opt, "create")->type == cJSON_True)
                containCreate = true;
            if(cJSON_GetObjectItem(opt, "exclusive") && cJSON_GetObjectItem(opt, "exclusive")->type == cJSON_True)
                exclusive = true;
        }
        
        if(exclusive) {
            if(FileCache::isDirectory(nativeURL+path)) {
                 cbc.error(NO_MODIFICATION_ALLOWED_ERR);
                return true;
            }
        }
        
        if(containCreate) {
            if(!FileCache::createDirectory(nativeURL+path)) {
                cbc.error(SECURITY_ERR);
                return true;
            }
        }                                                               
        cJSON* pJson =  makeEntryForUrl(nativeURL+path);     
        if(pJson != NULL) {
            cbc.success(pJson);
            cJSON_Delete(pJson);
        } else {
            cbc.error(NOT_FOUND_ERR);
        }
    } else if(actionAsString == "getFile") {
        if(cJSON_GetArraySize(args) < 2) {
            cbc.error(PATH_EXISTS_ERR);
            return true;
        }
        string dirname = cJSON_GetArrayItem(args, 0)->valuestring;
        string fileName = cJSON_GetArrayItem(args, 1)->valuestring;
        string nativeURL = CFilesystem::getNativeUrl(dirname);
        
        bool containCreate = false;
        if(cJSON_GetArraySize(args) >= 3) {
            cJSON* opt = cJSON_GetArrayItem(args, 2);
            if(cJSON_GetObjectItem(opt, "create")->type == cJSON_True)
                containCreate = true;
        }
        if(containCreate) {
            if(!FileCache::createFile(nativeURL+fileName)) {
                cbc.error(NOT_READABLE_ERR);
                return true;
            }
        } 
        cJSON* pJson =  makeEntryForUrl(nativeURL+fileName);     
       if(pJson != NULL) {
            cbc.success(pJson);
            cJSON_Delete(pJson);
        } else {
            cbc.error(PATH_EXISTS_ERR);
        }
    } else if(actionAsString == "remove") {
        if(cJSON_GetArraySize(args) < 1) {
            cbc.error(PATH_EXISTS_ERR);
            return true;
        }
        string fName = cJSON_GetArrayItem(args, 0)->valuestring;         
        string nativeURL = CFilesystem::getNativeUrl(fName);
        if(FileCache::deleteFile(nativeURL.c_str())) {
            cbc.success();
        } else {
            cbc.error(FileUtils::NO_MODIFICATION_ALLOWED_ERR);
        }
    } else if(actionAsString == "removeRecursively") {
        if(cJSON_GetArraySize(args) < 1) {
            cbc.error(PATH_EXISTS_ERR);
            return true;
        }
        string fName = cJSON_GetArrayItem(args, 0)->valuestring;         
        string nativeURL = CFilesystem::getNativeUrl(fName);
        FileCache::deleteDirectory(nativeURL.c_str());
        cbc.success();
    } else if(actionAsString == "moveTo") {
        if(cJSON_GetArraySize(args) < 3) {
            cbc.error(PATH_EXISTS_ERR);
            return true;
        }
        string fName = cJSON_GetArrayItem(args, 0)->valuestring;  
        string newParent = cJSON_GetArrayItem(args, 1)->valuestring;  
        string newName = cJSON_GetArrayItem(args, 2)->valuestring;  

        fName = CFilesystem::getNativeUrl(fName);
        newParent = CFilesystem::getNativeUrl(newParent);
        newParent += newName;
        if(fName != newParent && !FileCache::moveFile(fName, newParent)) {
            cbc.error(PATH_EXISTS_ERR);
            return true;
        }
        cJSON* pJson =  makeEntryForUrl(newParent);     
        if(pJson != NULL) {
            cbc.success(pJson);
            cJSON_Delete(pJson);
        } else {
            cbc.error(PATH_EXISTS_ERR);
        }
        return true;
    } else if(actionAsString == "copyTo") {
        if(cJSON_GetArraySize(args) < 3) {
            cbc.error(PATH_EXISTS_ERR);
            return true;
        }
        string fName = cJSON_GetArrayItem(args, 0)->valuestring;  
        string newParent = cJSON_GetArrayItem(args, 1)->valuestring;  
        string newName = cJSON_GetArrayItem(args, 2)->valuestring;  

        fName = CFilesystem::getNativeUrl(fName);
        newParent = CFilesystem::getNativeUrl(newParent);
        newParent += newName;
        if(fName != newParent && !FileCache::copyFile(fName, newParent)) {
            cbc.error(PATH_EXISTS_ERR);
            return true;
        }
        cJSON* pJson =  makeEntryForUrl(newParent);     
        if(pJson != NULL) {
            cbc.success(pJson);
            cJSON_Delete(pJson);
        } else {
            cbc.error(PATH_EXISTS_ERR);
        }
        return true;
    } else if(actionAsString == "readEntries") {
        if(cJSON_GetArraySize(args) < 1) {
            cbc.error(PATH_EXISTS_ERR);
            return true;
        }
        string directory = cJSON_GetArrayItem(args, 0)->valuestring;  
        directory = CFilesystem::getNativeUrl(directory);
        vector<string> vecFile;
        FileCache::getDirectoryFile(directory.c_str(), vecFile);
        cJSON* pJsonArray = cJSON_CreateArray();
        for(int i=0; i<vecFile.size(); i++) {
            cJSON* pJson =  makeEntryForUrl(vecFile[i]); 
            cJSON_AddItemToArray(pJsonArray, pJson);
        }
        cbc.success(pJsonArray);
        cJSON_Delete(pJsonArray);
        return true;
    } else if(actionAsString == "_getLocalFilesystemPath") {
        return true;
    } else {
        return false;
    }
    return true;
}

void FileUtils::pluginInitialize()
{
    m_vecFilesystems = CFilesystem::getFileSystem();
    return;
}

cJSON* FileUtils::requestAllPaths() 
{
    string strBaseDir = Application::g_databaseDir.substr(0, Application::g_databaseDir.find("database")-1);
    cJSON* pJson = cJSON_CreateObject();
    char szBuf[256];
    
    cJSON_AddStringToObject(pJson, "applicationDirectory", strBaseDir.c_str());
    
    sprintf(szBuf, "%s/base/files", strBaseDir.c_str());
    cJSON_AddStringToObject(pJson, "applicationStorageDirectory", szBuf);
    
    cJSON_AddStringToObject(pJson, "dataDirectory", szBuf);
    
    sprintf(szBuf, "%s/base/cache", strBaseDir.c_str());
    cJSON_AddStringToObject(pJson, "cacheDirectory", szBuf);
    
    sprintf(szBuf, "%s/base/files", strBaseDir.c_str());
    cJSON_AddStringToObject(pJson, "externalApplicationStorageDirectory", szBuf);
    
    sprintf(szBuf, "%s/base/files", strBaseDir.c_str());
    cJSON_AddStringToObject(pJson, "externalDataDirectory", szBuf);
    
    sprintf(szBuf, "%s/base/cache", strBaseDir.c_str());
    cJSON_AddStringToObject(pJson, "externalCacheDirectory", szBuf);
    
    sprintf(szBuf, "%s", strBaseDir.c_str());
    cJSON_AddStringToObject(pJson, "externalRootDirectory", szBuf);
    
    sprintf(szBuf, "%s/base/temp", strBaseDir.c_str());
    cJSON_AddStringToObject(pJson, "tempDirectory", szBuf);
    
    sprintf(szBuf, "%s/base/files", strBaseDir.c_str());
    cJSON_AddStringToObject(pJson, "syncedDataDirectory", szBuf);
    
    sprintf(szBuf, "%s/base/files", strBaseDir.c_str());
    cJSON_AddStringToObject(pJson, "documentsDirectory", szBuf);
    
    sprintf(szBuf, "%s/base/files", strBaseDir.c_str());
    cJSON_AddStringToObject(pJson, "sharedDirectory", szBuf);
    return pJson;
}

FileUtils::LocalFilesystemURL FileUtils::resolveNativeUri(const string & strFilePath) 
{
    LocalFilesystemURL inputURL;
    string strFilePathTmp = FileCache::urlDecode(strFilePath);
    if(strFilePathTmp.find("file://") == 0) {//uri转path
        char *pathResult = NULL;
        FileManagement_ErrCode ret = OH_FileUri_GetPathFromUri(strFilePathTmp.c_str(), strFilePathTmp.length(), &pathResult);
        if (ret == 0 && pathResult != NULL) {
            strFilePathTmp = pathResult;
            free(pathResult);
        } else {
            return inputURL;
        }
    }
    
    struct stat statBuf;
    int res = -1;
	if(stat(strFilePathTmp.c_str(), &statBuf) != 0) {//获取linux操作系统下文件的属性
        return inputURL;
    }
    
    if(S_ISDIR(statBuf.st_mode)) {
        inputURL.m_isDirectory = true;
    } else {
        inputURL.m_isDirectory = false;
        inputURL.m_lngSize = statBuf.st_size;
    }
    
    for(int i=0; i<m_vecFilesystems.size(); i++) {
        if(strFilePathTmp.find(m_vecFilesystems[i].m_strRootUri) != string::npos) {
            inputURL.m_strFsName = m_vecFilesystems[i].m_strName;
            break;
        }
    }
    
    inputURL.m_strUri = strFilePathTmp;
    if(inputURL.m_isDirectory) {
        inputURL.m_strPath =  strFilePathTmp;
        inputURL.m_strFileName = "";
    } else {
        if(strFilePathTmp.find_last_of("/") != string::npos) {
            inputURL.m_strPath = strFilePathTmp.substr(0, strFilePathTmp.find_last_of("/")+1);
            inputURL.m_strFileName = strFilePathTmp.substr(strFilePathTmp.find_last_of("/")+1);
        }
    }
   
    return inputURL;
}

cJSON* FileUtils::makeEntryForUrl(const string & strFilePath) 
{
    LocalFilesystemURL filesystem = resolveNativeUri(strFilePath);
    if(filesystem.m_strUri.empty()) 
        return NULL;
    
    cJSON* entry = cJSON_CreateObject();
    if(filesystem.m_isDirectory) {
        cJSON_AddTrueToObject(entry, "isDirectory");
        cJSON_AddFalseToObject(entry, "isFile");
    } else {
        cJSON_AddFalseToObject(entry, "isDirectory");
        cJSON_AddTrueToObject(entry, "isFile");
    }
    int isFilesystem = 1;
    if(filesystem.m_strFsName == "temporary")
        isFilesystem = 0;
    cJSON_AddStringToObject(entry, "name", filesystem.m_strFileName.c_str());
    cJSON_AddStringToObject(entry, "fullPath", filesystem.m_strUri.c_str());
    cJSON_AddStringToObject(entry, "filesystemName", filesystem.m_strFsName.c_str());
    cJSON_AddNumberToObject(entry, "filesystem", isFilesystem);
    cJSON_AddStringToObject(entry, "nativeURL", filesystem.m_strUri.c_str());
    return entry;
}

cJSON* FileUtils::getFileMetadataForLocalURL(const string& strFilePath, const string& strFullPath)
{
    string strFilePathTmp = FileCache::urlDecode(strFilePath);
    if(strFilePathTmp.find("file://") == 0) {//uri转path
        char *pathResult = NULL;
        FileManagement_ErrCode ret = OH_FileUri_GetPathFromUri(strFilePathTmp.c_str(), strFilePathTmp.length(), &pathResult);
        if (ret == 0 && pathResult != NULL) {
            strFilePathTmp = pathResult;
            free(pathResult);
        } else {
            return NULL;
        }
    }
    
    struct stat statBuf;
    int res = -1;
	if(stat(strFilePathTmp.c_str(), &statBuf) != 0) {//获取linux操作系统下文件的属性
        return NULL;
    }
    
    string strFileName;
    cJSON* pJson = cJSON_CreateObject();
    if(S_ISDIR(statBuf.st_mode)) {
        cJSON_AddNumberToObject(pJson, "size", 0);
    } else {
        cJSON_AddNumberToObject(pJson, "size", statBuf.st_size);
        if(strFilePathTmp.find_last_of("/") != string::npos) {
            strFileName = strFilePathTmp.substr(strFilePathTmp.find_last_of("/")+1);
        }
    }
    
    cJSON_AddStringToObject(pJson, "type", getMimeType(strFilePathTmp).c_str());
    cJSON_AddStringToObject(pJson, "name", strFileName.c_str());
    cJSON_AddStringToObject(pJson, "fullPath", strFilePathTmp.c_str());
    cJSON_AddNumberToObject(pJson, "lastModifiedDate", statBuf.st_mtime);
    return pJson;
}

string FileUtils::getMimeType(const string& strFilePath)
{
    if(strFilePath.find(".html") != std::string::npos) {
         return "text/html";
    }else if(strFilePath.find(".js") != std::string::npos) {
        return "text/javascript";
    }else if(strFilePath.find(".css") != std::string::npos) {
        return "text/css";
    }else if(strFilePath.find(".jpg") != std::string::npos) {
        return "image/jpeg";
    }else if(strFilePath.find(".jpeg") != std::string::npos) {
        return "image/jpeg";
    }else if(strFilePath.find(".png") != std::string::npos) {
        return "image/png";
    }else if(strFilePath.find(".woff") != std::string::npos) {
        return "font/woff";
    }else if(strFilePath.find(".mp4") != std::string::npos) {
        return "video/mp4";
    } else if(strFilePath.find(".mp3") != std::string::npos) {
        return "video/mp3";
    } else if(strFilePath.find(".3gp") != std::string::npos) {
        if(strFilePath.find("audio") != std::string::npos)
            return "audio/3ggp";
        else
          return "video/3ggp";  
    }  else if(strFilePath.find(".json") != std::string::npos) {
        return "application/json";
    } else if(strFilePath.find(".m4a") != std::string::npos) {
        return "audio/x-m4a";
    } else if(strFilePath.find(".ogg") != std::string::npos) {
        return "audio/ogg";
    } 
    return "";
}

bool FileUtils::onArKTsResult(cJSON* args)
{
    string content = cJSON_GetObjectItem(args, "content")->valuestring;
    cJSON* json = cJSON_GetObjectItem(args, "result");
    if(content == "GetFreeSpace") {
        long lngSize = 0;
        if(cJSON_GetArraySize(json) == 2) {
            cJSON* pOk = cJSON_GetArrayItem(json, 0);
            if(pOk != NULL) {
                string strOk = pOk->valuestring;
                if(strOk == "OK") {
                    cJSON* pSize = cJSON_GetArrayItem(json, 1);
                    if(pSize != NULL) {
                        lngSize = atol(pSize->valuestring);
                    }
                }
            }
        }
        PluginResult pluginResult(PluginResult::Status::OK, lngSize);
        m_cbc.sendPluginResult(pluginResult);
    }
    return true;
}
